
// This class allows to obtain position of cursor in the text area
// The position can be calculated as cursorX/cursorY or
// pointX/pointY
// See getCursorCoordinates and getPixelCoordinates

var EXPORTED_SYMBOLS = ["maxkir"];

var maxkir = {
    cursorPosition: function(element, padding) {
        this.element = element;
        this.padding = padding;
        var that = this;
    },


    getSelRange: function() {
        // thanks to http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/
        if( (typeof element.selectionStart == 'undefined') && document.selection ) {
            // The current selection
            var range = document.selection.createRange();
            // We'll use this as a 'dummy'
            var stored_range = range.duplicate();
            // Select all text
            if (element.type == 'text') {
                stored_range.moveStart('character', -element.value.length);
                stored_range.moveEnd('character', element.value.length);
            } else { // textarea
                stored_range.moveToElementText( element );
            }
            // Now move 'dummy' end point to end point of original range
            stored_range.setEndPoint( 'EndToEnd', range );
            // Now we can calculate start and end points
            var selectionStart = stored_range.text.length - range.text.length;
            var selectionEnd = selectionStart + range.text.length;
            return [selectionStart, selectionEnd];
        }
        return [element.selectionStart, element.selectionEnd];
    },


    cloneStyle: function(target, styleName) {
        var val = element.style[styleName];
        if (!val) {
            var css = document.defaultView.getComputedStyle(element, null);
            val = css ? css[styleName] : null;
        }
        if (val) {
            target.style[styleName] = val;
        }
    },

    getStringMetrics: function(s) {
        var widthElementId = "__widther";
        var div = document.getElementById(widthElementId);
        if (!div) {
            div = document.createElement("div");
            div.id = widthElementId;
            document.body.appendChild(div);

            div.style.position = 'absolute';
            div.style.left = '-10000px';
        }

        cloneStyle(div, 'fontSize');
        cloneStyle(div, 'fontFamily');
        cloneStyle(div, 'fontWeight');
        cloneStyle(div, 'fontVariant');
        cloneStyle(div, 'fontStyle');
        cloneStyle(div, 'textTransform');
        cloneStyle(div, 'lineHeight');

        div.style.width = '0';
        div.style.paddingLeft = that.padding + "px";

        div.innerHTML = s.replace(' ', "&nbsp;");
        div.style.width = 'auto';
        return [div.offsetWidth, div.offsetHeight];
    },


    splitToLines: function() {
        splitter = new maxkir.StringSplitter(function(s) {
            var metrics = that.getStringMetrics(s);
            //maxkir.info(s + " |||" + metrics)
            return metrics[0];
        });
        var innerAreaWidth = element.scrollWidth;
        innerAreaWidth -= 4;

        function get_selection_range() {
            try {
                return getSelRange();
            }
            catch(e) {
                return [0,0]
            }
        }

        var pos = get_selection_range()[0];
        return splitter.splitString(element.value.substr(0, pos), innerAreaWidth);
    },


    // width_provider_function is a function which takes one argument - a string
    // and returns width of the string

    // returns array of strings, as if they are splitted in textarea
    StringSplitter: function(width_provider_function) {
        this.get_width = width_provider_function;
    },


    init: function() {
        maxkir.cursorPosition.prototype.getPixelCoordinates = function() {
          var lines = this.splitToLines();
          var m = this.getStringMetrics(lines[lines.length - 1]);
          var w = m[0];
          var h = m[1] * lines.length - this.element.scrollTop + this.padding;
          return [w, h];
        };

        maxkir.StringSplitter.prototype.splitString = function(s, max_width) {

            if (s.length == 0) return [""];

            var prev_space_pos = -1;
            var width_exceeded = false;

            var that = this;
            var cut_off = function(idx) {
                var remaining = s.substr(idx + 1);
                if (remaining.length > 0) {
                    return [s.substr(0, idx + 1)].concat(that.splitString(remaining, max_width));
                }
                return [s.substr(0, idx + 1)]; 
            };

            for(var i = 0; i < s.length; i ++) {
            if (s.charAt(i) == ' ') {
                width_exceeded = this.get_width(s.substr(0, i)) > max_width;
                if (width_exceeded && prev_space_pos > 0) {
                    return cut_off(prev_space_pos);
                }
                if (width_exceeded) {
                    return cut_off(i);
                }
                prev_space_pos = i;
                }
                if (s.charAt(i) == '\n') {
                    return cut_off(i);
                }
            }
            if (prev_space_pos > 0 && this.get_width(s) > max_width) {
            return cut_off(prev_space_pos);
            }
            return [s];
        };

        maxkir.cursorPosition.prototype.getCursorCoordinates = function() {
            var lines = this.splitToLines();
            return [lines[lines.length - 1].length, lines.length];
        };
    }
};

